
jQuery.extend(
	fn, {
		// Default parameters of file browser
		options: {
			// The username of current user,
			// will be load from the container's title attribute if not provided via options
			username: undefined,
			// The default name of root folder,
			// may be overwritten by title attribute of folder list element
			rootFolder: "My Files",
			// Separator of file path
			folderSeparator: '|',
			// Html for folder names
			folderNameHtml: '<span class="icon-folder"></span><span>{folderName}</span>',
			// Regex to validate folder name
			folderName: /^[^\\\/\:\*?\<\>\|]+$/,
			// Regex to validate file name
			fileName: /^[^\\\/\:\*?\<\>\|]+$/,
			// Timeout for ajax request, in ms
			ajaxTimeout: 10000,
			// Selector for the folder list, should be a DOM element containing the list
			folderList: '#folderListPanel',
			// Selector for the file list, should be a DOM element containing the list
			fileList: '#fileListPanel',
			// Selector for the create folder button
			buttonCreateFolder: '#buttonCreateFolder',
			// Selector for the rename folder button
			buttonRenameFolder: '#buttonRenameFolder',
			// Selector for the delete folder button
			buttonDeleteFolder: '#buttonDeleteFolder',
			// Selector for the move folder button
			buttonMoveFolder: '#buttonMoveFolder',
			// Selector for the refresh folders button
			buttonRefreshFolders: '#buttonRefreshFolderList',
			// Selector for the refresh files button
			buttonRefreshFiles: '#buttonRefreshFileList',
			// Selector for the upload file button
			buttonUploadFile: '#buttonUploadFile',
			// Selector for the container of message
			statusMessage: "#statusMessage",
			// Status consider as an error
			errorStatus: ['Error', 'NotFound', 
				'AlreadyExist', 'FolderNotFound',
				'FolderLimitExceed', 'FileLimitExceed',
				'QuotaExceed', 'FileSizeLimitExceed'],
			// Settings for file operations
			file: {
				// Settings for download file
				download: {
					// Url to request for downloading file
					url: '/UserFile/Download?username={username}&path={path}',
					// Additional data to send with the request
					data: { }
				}, // End of download
				// Settings for moving file
				move: {
					// Url to request for moving file
					url: '/UserFile/FileMove?srcPath={srcPath}&destPath={destPath}',
					// Method for ajax request
					method: 'GET',
					// Additional data to send with the request
					data: { }
				}, // End of move
				// Settings for deleting file
				del: {
					// Url to request for deleting file
					url: '/UserFile/FileDelete?path={path}',
					// Method for ajax request
					method: 'GET',
					// Additional data to send with the request
					data: { }
				}, // End of delete
				// Settings for listing file under a folder
				list: {
					// Url to request for listing file.
					// path is the folde path to rquest
					url: '/UserFile/FileList?path={path}',
					// Method for ajax request
					method: 'GET',
					//Additional data to send with the request
					data: { }
				}, // End of listing
				// Settings for uploading file
				upload: {
					// Url to request for uploading file
					url: '/UserFile/FileUpload',
					// The name of the file input
					fileName: 'fileUploaded',
					// The name of the hidden iframe,
					// a random id will be used if unset
					frameName: undefined,
					// Additional data to send with the request
					data: { }
				} // End of upload
			}, // End of file
			// Settings for folder operations
			folder: {
				// Settings for creating folder
				create: {
					// Url to request for creating folder
					url: '/UserFile/FolderCreate?path={path}',
					// Method for ajax request
					method: 'GET',
					// Additional data to send with the request
					data: { }
				}, // End of move
				// Settings for moving folder
				move: {
					// Url to request for moving folder
					url: '/UserFile/FolderMove?srcPath={srcPath}&destPath={destPath}',
					// Method for ajax request
					method: 'GET',
					// Additional data to send with the request
					data: { }
				}, // End of move
				// Settings for deleting folder
				del: {
					// Url to request for deleting folder
					url: '/UserFile/FolderDelete?path={path}',
					// Method for ajax request
					method: 'GET',
					// Additional data to send with the request
					data: { }
				}, // End of delete
				// Settings for listing folder
				list: {
					// Url to request for listing folder
					url: '/UserFile/FolderList',
					// Method for ajax request
					method: 'GET',
					//Additional data to send with the request
					data: { }
				} // End of listing
			}, // End of folder
			// CSS classes used by the script
			classes: {
				// The class for current folder
				folderSelected: 'current-folder',
				// The class for disabled button
				buttonDisabled: 'button-disabled',		
				// The class for container of file list
				fileList: 'file-list',		
				// The class for container of file list while the list is empty
				fileListEmpty: 'file-list-empty',
				// The class for the icon of file name
				fileNameIcon: 'icon-file-name',		
				// The class for file name
				fileName: 'file-name',
				// The class for file size
				fileSize: 'file-size',			
				// The class for file actions
				fileActions: 'file-actions',
				// The class for file link button
				fileActionLink: 'file-action-link',	
				// The class for download file button
				fileActionDownload: 'file-action-download',				
				// The class for rename file button
				fileActionRename: 'file-action-rename',				
				// The class for move file button
				fileActionMove: 'file-action-move',				
				// The class for delete file button
				fileActionDelete: 'file-action-delete',				
				// The class for container of folder list
				folderList: 'folder-list',
				// The class for the text of folder item
				folderNameText: 'folder-name-text',		
				// The class for the icon of folder item
				folderIcon: 'icon-folder',
				// The class for the icon in the end of folder item
				folderTailIcon: 'icon-folder-end',
				// The class for the bullet of folder item
				folderBullet: 'folder-bullet',
				// The class for the bullet of opened folder item
				folderBulletOpened: 'folder-bullet-opened',
				// The class for the bullet of closed folder item
				folderBulletClosed: 'folder-bullet-closed',	
				// The class for folder name
				folderName: 'folder-name',
				// The class for folder name of current folder
				folderNameSelected: 'folder-name-selected',
				// The class for normal status message
				statusInfo: 'status-info',				
				// The class for error status message
				statusError: 'status-error',				
				// The class for warning status message
				statusWarn: 'status-warn',
				// The class for status message icon
				statusIcon: 'icon-status'
			},
			texts: {
			}
		}, // End of settings
		init: function(elem, options) {
			var qtfile = this,
			// Apply user options
			options = jQuery.extend(qtfile.options, options);

			qtfile.context = jQuery(elem);

			// Retrieve username if needed
			options.username = options.username ||
				jQuery.trim(qtfile.context.attr(AttrTitle));
			
			// Not enough information to build file browser
			if (qtfile.context.size() != 1 || !options.username) 
				return;
			
			qtfile.context.removeAttr(AttrTitle);
			
			options.errorStatus = '|' + options.errorStatus.join('|') + '|';
			
			qtfile.initFolders();
			qtfile.initFiles();
			qtfile.initButtons();
			
			qtfile.initFileDetails();
		},
		find: function(selector) {
			return this.context.find(selector);
		},
		loc: function(text) {
			return this.options.texts[text] || text;
		},
		// Combines two parts of patg
		combinePath: function(part1, part2) {
			if (part1.length > 0) 
				return part1 + this.options.folderSeparator + part2;
			return part2;
		}, // End of combinePath()
		splitPath: function(path) {
			var lastSp = path.lastIndexOf(this.options.folderSeparator);
			var name = path.substr(lastSp + 1);
			var parent = lastSp < 0 ? '' : path.substr(0, lastSp);
			return {
				parent: parent,
				name: name
			};
		},
		// Shows a status message
		showStatus: function(message, cssClassName, count) {
			var qtfile = this, options = qtfile.options,
				msgText = qtfile.loc(message),
				className = cssClassName || options.classes.statusInfo,
				msg = jQuery(HtmlTagSpan).addClass(className)
					.html(msgText)
					.prepend(jQuery(HtmlTagSpan).addClass(options.classes.statusIcon));

			qtfile.find(options.statusMessage).empty()
				.append(msg);
		}, // End of showStatusMessage()
		// Trys to lock the file browser
		tryLock: function(statusMsg, lockingMsg) {
			var qtfile = this;
			if (qtfile.isLocking) {
				alert(qtfile.lockingMessage);
				return false;
			}
			qtfile.isLocking = true;
			qtfile.showStatus(statusMsg);
			qtfile.lockingMessage = lockingMsg;
			return true;
		}, // End of tryLock()
		// Unlocks the file browser
		unlock: function(statusMsg, className) {
			var qtfile = this;
			qtfile.isLocking = false;
			qtfile.lockingMessage = null;
			if (statusMsg) {
				qtfile.showStatus(statusMsg, className);
			} else {
				qtfile.find(qtfile.options.statusMessage).empty();
			}
		}, // End of unlock()
		// Sends an ajax request
		request: function(requestInfo, data,
			onSuccess, // function(data, textStatus) { }
			onError, // function(XMLHttpRequest, textStatus, errorThrown) { }
			onComplete // function(XMLHttpRequest, textStatus) { }
		) {
			var qtfile = this, options = qtfile.options,
		
				// Combine request data
				combinedData = jQuery.extend({ }, requestInfo.data, {
						username: options.username
					}, data),
				
				url = formatUrl(requestInfo.url, combinedData);
			
			jQuery.ajax({
				url: url,
				data: combinedData,
				type: requestInfo.method,
				success: onSuccess,
				error: onError,
				complete: onComplete,
				dataType: 'json',
				cache: false,
				timeout: options.ajaxTimeout
			});
		}, // End of request()
		statusClass: function(data) {
			var qtfile = this, classes = qtfile.options.classes;
			return data.succeed ? classes.statusInfo :
				qtfile.options.errorStatus.indexOf('|' + data.status + '|') < 0 ?
				classes.statusWarn : classes.statusError;
		}
	});
